﻿using Firefly.Framework.ContentManagement;
using Firefly.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Firefly.Framework.Components.Terrain
{
    public class TerrainShader : ShaderProxy, IShaderProxy
    {
        public Vector3 SunlightDirection
        {
            get
            {
                return Effect.Parameters["SunlightDirection"].GetValueVector3();
            }
            set
            {
                Vector3 sunlightRealVector = value;
                float tempZ = sunlightRealVector.Z;
                sunlightRealVector.Z = sunlightRealVector.Y;
                sunlightRealVector.Y = tempZ;
                Effect.Parameters["SunlightDirection"].SetValue(sunlightRealVector);
            }
        }
        public Vector3 SunlightColor
        {
            get { return Effect.Parameters["SunlightColor"].GetValueVector3(); }
            set { Effect.Parameters["SunlightColor"].SetValue(value); }
        }
        public Vector3 AmbientLightColor
        {
            get { return Effect.Parameters["AmbientLightColor"].GetValueVector3(); }
            set { Effect.Parameters["AmbientLightColor"].SetValue(value); }
        }
        public bool HighQualityDetailMapping
        {
            get { return Effect.Parameters["HighQualityDetailMapping"].GetValueBoolean(); }
            set { Effect.Parameters["HighQualityDetailMapping"].SetValue(value); }
        }
        public float DetailScale
        {
            get { return Effect.Parameters["DetailScale"].GetValueSingle(); }
            set { Effect.Parameters["DetailScale"].SetValue(value); }
        }
        public float DiffuseScale
        {
            get { return Effect.Parameters["DiffuseScale"].GetValueSingle(); }
            set { Effect.Parameters["DiffuseScale"].SetValue(value); }
        }
        public string BlendTextureAsset { get; set; }
        public Texture2D BlendTexture
        {
            get { return Effect.Parameters["BlendTexture"].GetValueTexture2D(); }
            set { Effect.Parameters["BlendTexture"].SetValue(value); }
        }
        public string BlackTextureAsset { get; set; }
        public Texture2D BlackTexture
        {
            get { return Effect.Parameters["BlackTexture"].GetValueTexture2D(); }
            set { Effect.Parameters["BlackTexture"].SetValue(value); }
        }
        public string RedTextureAsset { get; set; }
        public Texture2D RedTexture
        {
            get { return Effect.Parameters["RedTexture"].GetValueTexture2D(); }
            set { Effect.Parameters["RedTexture"].SetValue(value); }
        }
        public string GreenTextureAsset { get; set; }
        public Texture2D GreenTexture
        {
            get { return Effect.Parameters["GreenTexture"].GetValueTexture2D(); }
            set { Effect.Parameters["GreenTexture"].SetValue(value); }
        }
        public string BlueTextureAsset { get; set; }
        public Texture2D BlueTexture
        {
            get { return Effect.Parameters["BlueTexture"].GetValueTexture2D(); }
            set { Effect.Parameters["BlueTexture"].SetValue(value); }
        }
        public string DetailTextureAsset { get; set; }
        public Texture2D DetailTexture
        {
            get { return Effect.Parameters["DetailTexture"].GetValueTexture2D(); }
            set { Effect.Parameters["DetailTexture"].SetValue(value); }
        }
        public Texture2D NormalTexture
        {
            get { return Effect.Parameters["NormalTexture"].GetValueTexture2D(); }
            set { Effect.Parameters["NormalTexture"].SetValue(value); }
        }
        public float DetailMapStrength
        {
            get { return Effect.Parameters["DetailMapStrength"].GetValueSingle(); }
            set { Effect.Parameters["DetailMapStrength"].SetValue(value); }
        }
        public float GlobalScale
        {
            get { return Effect.Parameters["GlobalScale"].GetValueSingle(); }
            set { Effect.Parameters["GlobalScale"].SetValue(value); }
        }

        public TerrainShader(IQuadTerrain parent)
            : this(parent, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty)
        {
        }

        public TerrainShader(IQuadTerrain parent, string blendTexture, string baseTexture, string redTexture, string greenTexture, string blueTexture, string detailTexture)
            : base(parent)
        {
            EffectName = "Effects\\Terrain\\Terrain";
            BlendTextureAsset = blendTexture;
            BlackTextureAsset = baseTexture;
            RedTextureAsset = redTexture;
            GreenTextureAsset = greenTexture;
            BlueTextureAsset = blueTexture;
            DetailTextureAsset = detailTexture;
        }

        #region IShaderProxy Members

        public override void Draw(GameTime gameTime)
        {
            QuadTerrain t = Parent as QuadTerrain;
            Effect.Begin();

            foreach (EffectPass pass in Effect.CurrentTechnique.Passes)
            {
                pass.Begin();
                t.VertexMap.DrawIndexedPrimitives();
                pass.End();
            }

            Effect.End();
        }

        #endregion

        #region IHasContent Members

        public override void LoadContent()
        {
            Effect = ContentService.Instance.Load<Effect>(EffectName);
            Effect.CurrentTechnique = Effect.Techniques["Render"];
            SunlightColor = new Vector3(2.3f, 2f, 1.8f);
            AmbientLightColor = new Vector3(1.3f, 1.3f, 1.3f);
            DiffuseScale = 2.5f;
            DetailScale = 0.1f;
            DetailMapStrength = 2.0f;
            HighQualityDetailMapping = true;

            if (string.IsNullOrEmpty(BlendTextureAsset))
            {
                BlendTextureAsset = "Textures\\Terrain\\Blend";
            }

            if (string.IsNullOrEmpty(BlackTextureAsset))
            {
                BlackTextureAsset = "Textures\\Terrain\\TexBlack";
            }

            if (string.IsNullOrEmpty(RedTextureAsset))
            {
                RedTextureAsset = "Textures\\Terrain\\TexRed";
            }

            if (string.IsNullOrEmpty(GreenTextureAsset))
            {
                GreenTextureAsset = "Textures\\Terrain\\TexGreen";
            }

            if (string.IsNullOrEmpty(BlueTextureAsset))
            {
                BlueTextureAsset = "Textures\\Terrain\\TexBlue";
            }

            if (string.IsNullOrEmpty(DetailTextureAsset))
            {
                DetailTextureAsset = "Textures\\Terrain\\Detail";
            }

            BlendTexture = ContentService.Instance.Load<Texture2D>(BlendTextureAsset);
            BlackTexture = ContentService.Instance.Load<Texture2D>(BlackTextureAsset);
            RedTexture = ContentService.Instance.Load<Texture2D>(RedTextureAsset);
            GreenTexture = ContentService.Instance.Load<Texture2D>(GreenTextureAsset);
            BlueTexture = ContentService.Instance.Load<Texture2D>(BlueTextureAsset);
            DetailTexture = ContentService.Instance.Load<Texture2D>(DetailTextureAsset);
        }

        public override void UnloadContent()
        {
            ContentService.Instance.Release(EffectName);
            ContentService.Instance.Release(BlendTextureAsset);
            ContentService.Instance.Release(BlackTextureAsset);
            ContentService.Instance.Release(RedTextureAsset);
            ContentService.Instance.Release(GreenTextureAsset);
            ContentService.Instance.Release(BlueTextureAsset);
            ContentService.Instance.Release(DetailTextureAsset);
        }

        #endregion

        #region IDisposable Members

        ~TerrainShader()
        {
            Dispose(false);
        }

        #endregion
    }
}
